//
// Created by 陈成 on 2019/9/19.
//

#include "InstS.h"

InstS::InstS(uint32_t pc, sc_bv<32> value, RegBank<REG_NUM> *r, RegBank<CSR_NUM> *csr, Mem *m) :
        Inst(pc, value, r, csr, m),
        imm   ((value.range(31, 25),
                value.range(11, 7))),
        rs2   (value.range(24, 20)),
        rs1   (value.range(19, 15)),
        funct3(value.range(14, 12)),
        opcode(value.range( 6,  0)) {

}

uint32_t
InstS::exec() {
    switch (opcode.to_uint()) {
    case 0b0100111: // STORE
        handleType0();
        break;
    default:
        assert(false);
        break;
    }
    return pc + 4;
}

void InstS::handleType0() {
    uint32_t u32_rs2 = r->read(rs2.to_uint()).to_uint();
    uint32_t u32_rs1 = r->read(rs1.to_uint()).to_uint();
    int32_t  i32_imm = imm.to_int();

    switch (funct3.to_uint()) {
    case 0b000: // SW
        m->write(u32_rs1 + i32_imm, u32_rs2);

        LOG("SW RS1: %d, RS2: %d, IMM: %d", rs1.to_uint(), rs2.to_uint(), imm.to_uint());
        LOG("Store %d to addr: %d + %d", u32_rs2, u32_rs1, i32_imm);
        break;
    case 0b001: // SH
        m->write(u32_rs1 + i32_imm, u32_rs2 & 0xffff);
        break;
    case 0b010: // SB
        m->write(u32_rs1 + i32_imm, u32_rs2 & 0xff);
        break;
    default:
        assert(false);
        break;
    }
}
